<?php
/**
 * 上传文件的处理
 * 
 * @copyright  Copyright (c) 2012 www.Mediad.cn
 * @license    New BSD License
*/
class Mediad2_Utility_FileHandle extends Mediad2_Utility_Abstract
{
	/**
	 * 上传文件的接收和处理
	 * @param string $save_path 上传文件的保存路径
	 * @param string $upload_name 上传控件的名称或ID
	 * @return Mediad2_Model_Result
	 */
	public function upload($save_path, $upload_name='Filedata')
	{
		header('Content-type:text/html; charset=utf-8');
	
		// Code for Session Cookie workaround
		if (isset($this->httpdata["PHPSESSID"])) {
			session_id($this->httpdata["PHPSESSID"]);
		}
	
		if (empty($_FILES)) { //判断_FILES是否为空，即是否存在上传文件
	
			//判断上传文件是否超出了PHP限制的最大规模 post_max_size
			$POST_MAX_SIZE = ini_get('post_max_size');
			$unit = strtoupper(substr($POST_MAX_SIZE, -1));
			$multiplier = ($unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1)));
			if ((int)$_SERVER['CONTENT_LENGTH'] > $multiplier*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) {
				header("HTTP/1.1 500 Internal Server Error");
				return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,'未能成功上传文件，请检查文件大小是否超出限制规模?');
			} else {
				return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,'未能成功上传文件，请重试');
			}
	
		} else {
			return $this->handleSingleUploadFile($upload_name, $save_path);
		}
	}
	
	/**
	 * 处理单个上传文件
	 *
	 * @param string $upload_name 上传控件的名称或ID
	 * @param string $save_path 上传文件的保存路径
	 * @return Mediad2_Model_Result 
	 */
	public function handleSingleUploadFile($upload_name, $save_path)
	{
		/*
		 * var
		*/
		//文件名的最大长度
		$max_filename_length = 260;
		//文件的最大规模
		$max_filesize_in_bytes = MAX_FILESIZE_IN_BYTES;
		//允许的文件名字符
		$valid_chars_regex = '.A-Z0-9_ !@#$%^&()+={}\[\]\',~`-';
		//上传错误提示信息
		$uploadErrors = array (
				0 => '上传成功',
				1 => '上传的文件超过了限制的值', //upload_max_filesize
				2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
				3 => '文件只有部分被上传',
				4 => '没有文件被上传',
				6 => '临时目录路径有误', //Missing a temporary folder
		);
		//是否允许覆盖相同文件
		$accept_overwrite = 1;
		//临时文件名
		$upload_temp_file_name = $_FILES[$upload_name]["tmp_name"];
		//上传文件名
		//$upload_file_name 	= $this->httpdata['filename'] ? base64_decode(str_replace('@@@', '+', $this->httpdata['filename'])) : $_FILES[$upload_name]['name'];
		//获取$_FILES[$upload_name]['name'] 时乱码;修改代码为一下
		//test!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! by vincent
		$upload_file_name 	= isset($_REQUEST['filename']) ? $this->decodeRequest($_REQUEST['filename']) : $_FILES[$upload_name]['name'];
		
		//上传文件大小
		$upload_file_size = $_FILES[$upload_name]['size'];
	
		//获取后缀名
		$fixs	= explode (".", $upload_file_name);
		
		$counts = count ($fixs) - 1;
		$fix    = strtolower($fixs[$counts]);
		
		//创建路径
		if (!is_dir ($save_path."/".date('Ymd'))){
			mkdir ($save_path."/".date('Ymd'), 0777);
			chmod ($save_path."/".date('Ymd'), 0777);
		}
	
		//获取文件名和文件路径
		$file_name = str_replace("/", "", substr (md5 (date('YmdHis')), 5, 10).rand(10000, 99999).".".$fix);
		$save_file_path = date ('Ymd')."/".$file_name;
	
		/*
		 * 验证
		*/
		//验证1：指定名称的上传文件为空
		if (!isset($_FILES[$upload_name])) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"没有发现指定名称[".$upload_name."]的上传文件");
		}
		//验证2：上传过程中存在错误
		if (isset($_FILES[$upload_name]["error"]) && $_FILES[$upload_name]["error"] != 0) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,$uploadErrors[$_FILES[$upload_name]["error"]]);
		}
		//验证3：上传文件测试
		if (!isset($upload_temp_file_name) || !@is_uploaded_file($upload_temp_file_name)) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"未通过上传文件测试");
		}
		//验证4：上传文件没有名称
		if (!isset($upload_file_name)) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"上传文件没有名称");
		}
		//验证5：上传文件规模应小于业务规定的最大文件规模
		$file_size = @filesize($_FILES[$upload_name]["tmp_name"]);
		if ($file_size <= 0) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"上传文件的大小为0");
		}
		if (!$file_size || $file_size > $max_filesize_in_bytes) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"上传文件的大小超过了限制");
		}
		//验证6：文件名应符合正则表达式的规则
		$file_name = preg_replace('/[^'.$valid_chars_regex.']|\.+$/i', "", basename($upload_file_name));
		if (strlen($file_name) == 0 || strlen($file_name) > $max_filename_length) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"文件名有误");
		}
		//验证7：判断是否存在同名文件
		if (file_exists($save_path."/".$save_file_path) && !$accept_overwrite) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"存在同名文件");
		}
		//验证8：判断文件类型是否是允许上传的文件类型
		// 		$extension_whitelist = array("jpg", "gif", "png","rar","jpeg");	// Allowed file extensions
		// 		$is_valid_extension = false;
		// 		foreach ($extension_whitelist as $extension) {
		// 			if (strcasecmp($fix, $extension) == 0) {
		// 				$is_valid_extension = true;
		// 				break;
		// 			}
		// 		}
		// 		if (!$is_valid_extension) {
		// 			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"无效的文件类型");
		// 		}
		
		/*
		 * 处理文件
		*/
		//移动临时文件到指定的文件目录
		if(!move_uploaded_file ($upload_temp_file_name, $save_path.$save_file_path)) {
			return $this->returnResult(Mediad2_Model_Result::CODE_FAILURE,"file cann't save 153 ");
		} else {
			chmod ($save_path.$save_file_path, 0777);
			$imgdata = $this->getfileimg($save_file_path);
	
			$data = array();
			$data['filepath'] = $save_file_path;
			$data['filesize'] = $file_size;
			$data['filename'] = $upload_file_name;
			$data['filetype'] = $fix;
			$data['fileimg']  = $imgdata['img_thumb'];
			$data['imgdate']  = $imgdata['img_date'];
			$data['imginfo']  = $imgdata['img_info'];
// 			$data['addtime']  = $this->httpdata['addtime'] ? $this->httpdata['addtime'] : time();
			$data['addtime']  = isset($_REQUEST['addtime']) ? $_REQUEST['addtime'] : time();
			$data['lastime']  = $data['addtime'];
			return $this->returnResult(Mediad2_Model_Result::CODE_SUCCESS,null,$data);
		}
	}
	
	/**
	 *  @param $local(string,input的name值), $path(要上传的路径)
	 *	@return $file_name(上传后的文件名，不含$path)
	 *	@time 2012.11.10 16:58 vincent
	 *	@lastime 2012.11.10 16:58 vincent
	 */
	public function TM_upload ($local, $path)
	{
		if (is_array($_FILES[$local]['name'])) {
			$counts = count($_FILES[$local]['name']);
			for ($i = 0; $i < $counts; $i++){
				$fixs        = explode (".", $_FILES[$local]['name'][$i]);
				$counts      = count ($fixs) - 1;
				$fix         = $fixs[$counts];
	
				if (!is_dir($path."/".date(Ymd))){
					mkdir ($path."/".date(Ymd), 0777);
					chmod ($path."/".date(Ymd), 0777);
				}
				$name_path = str_replace("/", "", substr (md5 (date(YmdHis)), 5, 10).".".$fix);
				$file_name   = date("Ymd")."/".$name_path;				

				if(move_uploaded_file ($_FILES[$local]['tmp_name'][$i], $path."/".$file_name)){
					chmod ($path."/".$file_name, 0777);
					$names[] = $file_name;
				} else {
					$names[] = "";
				}
				
			}
			return $names;
		} else {
			$fixs        = explode (".", $_FILES[$local]['name']);
			$counts      = count ($fixs) - 1;
			$fix         = strtolower($fixs[$counts]);
	
			if (!is_dir ($path."/".date(Ymd))){
				mkdir ($path."/".date(Ymd), 0777);
				chmod ($path."/".date(Ymd), 0777);
			}
	
			$name_path = str_replace("/", "", substr (md5 (date(YmdHis)), 5, 10).rand(10000, 99999).".".$fix);
			$file_name   = date ('Ymd')."/".$name_path;
			if(move_uploaded_file ($_FILES[$local]['tmp_name'], $path."/".$file_name)){
				chmod ($path."/".$file_name, 0777);
				return $file_name;
			} else {
				return false;
			}
			
		}
	}
	
	/**
	 * 获得文件缩略图等信息
	 * @param string $filename
	 * @param boolean $isGetImageInfo
	 */
	public function getfileimg($filename, $isGetImageInfo=false) 
	{
		$result = array(
				'img_thumb' => '',
				'img_name' 	=> '',
				'img_info' 	=> '',
				'img_date'	=> 0,
			);
		
		$fixs        = explode (".", $filename);
		$counts      = count ($fixs) - 1;
		$fix         = strtolower($fixs[$counts]);
		
		$dictUtil 	= Mediad2_Service_Util_Dict::getInstance();
		$ext  		= $dictUtil->getId('fileExtension');
		$img 		= explode(",", $ext['data']['image']);
		$music 		= explode(",", $ext['data']['music']);
		$video 		= explode(",", $ext['data']['video']);
		$zip 		= explode(",", $ext['data']['doc']);
		$book 		= explode(",", $ext['data']['book']);
		
		$arrExt = array_merge($img, $music, $video, $zip, $book);
		
		$imgName = 'skin/img/extview/default.png';
		$result['img_thumb']= $imgName;
		$result['img_name'] = $imgName;
		
		if (in_array($fix,$arrExt)) {
			
			$imgName = 'skin/img/extview/' . $fix. '.png';
			$result['img_thumb']= $imgName;
			$result['img_name'] = $imgName;
			
			if (in_array($fix, $img)) {

				$file = FILE_LOCATION . $filename;
				$path = ROOT_PATH.THUMB_PATH;
				$path_review = ROOT_PATH.REVIEW_PATH;
	
				if (!is_dir($path.'/'.date('Ymd'))) {
					mkdir($path.'/'.date('Ymd'), 0777);
					chmod($path.'/'.date('Ymd'), 0777);
				}
				if (!is_dir($path_review.'/'.date('Ymd'))) {
					mkdir($path_review.'/'.date('Ymd'), 0777);
					chmod($path_review.'/'.date('Ymd'), 0777);
				}

				//$this->makethumb($file,$path.$filename,110,110);
				//$this->makethumb($file,$path_review.$filename,440,440);
				
				try {
					$this->makeSamllPicture($file,$path.$filename,$path_review.$filename,Array(220,220),Array(800,800));
					//取消review图  20130824
					//$this->makeSamllPicture($file,$path.$filename);
				} catch (Exception $e) {
					$this->helper->log("make samll picture error:".$e->getMessage());
				}
				
				$imgName = THUMB_PATH. $filename;
				$result['img_thumb'] = $imgName;
				$result['img_name'] = $filename;
				
				// 如果是图片,那么还需要得到imginfo和拍摄时间
				if ($isGetImageInfo) {
					$img_info = '';
					$img_date = time();
					
					$img_info =  $this->getImageInfo(FILE_LOCATION . $filename);
					$img_date = !empty($img_info['拍摄时间']) ? strtotime($img_info['拍摄时间']) : 0;
					
					$result['img_info'] = $img_info;
					$result['img_date'] = $img_date;
				}
				
			}
		}
		return $result;
	}
	

	/**
	 * @param 图片文件路径$srcFile
	 * @param thumb名称 $thumbName
	 * @param review名称 $reviewName
	 * @param thumb大小$thumbSize
	 * @param review大小$reviewSize
	 * @param 品质$rate
	 * @return boolean
	 */
	public function makeSamllPicture($srcFile, $srcThumb, $srcReview = null, $thumb = Array(220,220), $review = Array(1024,768), $rate = 100)
	{
		$data = GetImageSize ( $srcFile );
		switch ($data [2]) {
			case 1 :
				$raw = @ImageCreateFromGIF ( $srcFile );
				break;
			case 2 :
				$raw = @ImageCreateFromJPEG ( $srcFile );
				break;
			case 3 :
				$raw = @ImageCreateFromPNG ( $srcFile );
				break;
			case 6:
				$raw = @$this->imageCreateFromBMP( $srcFile );
				break;
		}
	
		if (!$raw) return ;
		$width_raw = ImageSX ( $raw );//宽度
		$height_raw = ImageSY ( $raw );//高度
	
		list($width_thumb,$height_thumb) = $thumb;//缩略图大小
		list($width_review,$height_review) = $review;//review大小
	
		//2:判断图片比例
		$pictureData = $this->getRate($width_raw, $height_raw,$width_review,$height_review);//获取review比例大小
	
		$width_review = $pictureData['width'];//展示图的宽度
		$height_review = $pictureData['height'];//展示图的高度
	
	
		//3:切割正方形thumb缩略图
		//如果图片小于缩略图的值,直接拷贝成缩略图
		if($width_raw < $width_thumb && $height_raw < $height_thumb){
			copy($srcFile, $srcThumb);			
		}else{
			//获取图片模式,裁剪图片后再缩小到缩小图的比例
	
			$minLen = $width_raw > $height_raw ?$height_raw: $width_raw;
	
			$dstX = 0;
			$dstY = 0;
	
			if($pictureData['mode']%2==0){//4:3
				$dstX = floor ( ($width_raw - $minLen) / 2 );
			}else{//3:4
				$dstY = floor ( ($height_raw - $minLen) / 2 );
			}
	
			$tempImg = ImageCreateTrueColor ( $minLen, $minLen );
			$thumbImg = ImageCreateTrueColor ( $width_thumb, $height_thumb );
	
			imagecopyresampled($tempImg, $raw, 0, 0, $dstX, $dstY, $width_raw, $height_raw, $width_raw, $height_raw);
			imagecopyresampled($thumbImg, $tempImg, 0,0,0,0, $width_thumb, $height_thumb, $minLen, $minLen);
	
			ImageJpeg ( $thumbImg, $srcThumb, $rate );
			imagedestroy ( $tempImg );
			imagedestroy ( $thumbImg );
		}
	
		//4:按比例生成review图
		//如果图片小于展示图的值,直接拷贝成展示图
		if (!empty($srcReview)) {
			if($width_raw < $width_review && $height_raw < $height_review){
				copy($srcFile, $srcReview);
			}else{
				$reviewImg = ImageCreateTrueColor ( $width_review, $height_review );
				//目标图像|被拷贝图像|目标x坐标|目标y坐标|拷贝x坐标|拷贝y坐标|拷贝宽度|拷贝高度
				//ImageCopyResized ( $reviewImg, $raw, 0, 0, 0, 0, $width_review, $height_review, $width_raw, $height_raw );
				//更清晰的图片 20130319 vincent
				imagecopyresampled ( $reviewImg, $raw, 0, 0, 0, 0, $width_review, $height_review, $width_raw, $height_raw );
	
				ImageJpeg ( $reviewImg, $srcReview, $rate );
				imagedestroy ( $reviewImg );
			}
		}
	
		//删除图像
		imagedestroy ( $raw );
	}
	
	/*构造函数-生成缩略图+水印,参数说明:
		$srcFile-图片文件名,
		$dstFile-另存文件名,
		$markwords-水印文字,
		$markimage-水印图片,
		$dstW-图片保存宽度,
		$dstH-图片保存高度,
		$rate-图片保存品质
	*/
	public function makethumb($srcFile, $dstFile, $dstW, $dstH, $rate = 100, $markwords = null, $markimage = null) 
	{
		$data = GetImageSize ( $srcFile );
		switch ($data [2]) {
			case 1 :
				$im = @ImageCreateFromGIF ( $srcFile );
				break;
			case 2 :
				$im = @ImageCreateFromJPEG ( $srcFile );
				break;
			case 3 :
				$im = @ImageCreateFromPNG ( $srcFile );
				break;
			case 6:
				$im = @$this->imageCreateFromBMP( $srcFile );
				break;
		}
	
		if (!$im) return False;
		$srcW = ImageSX ( $im );
		$srcH = ImageSY ( $im );
		$dstX = 0;
		$dstY = 0;
	
		if ($srcW * $dstH > $srcH * $dstW) {
			$fdstH = round ( $srcH * $dstW / $srcW );
			$dstY = floor ( ($dstH - $fdstH) / 2 );
			$fdstW = $dstW;
		} else {
			$fdstW = round ( $srcW * $dstH / $srcH );
			$dstX = floor ( ($dstW - $fdstW) / 2 );
			$fdstH = $dstH;
		}
	
		$ni = ImageCreateTrueColor ( $fdstW, $fdstH );
		$dstX = ($dstX < 0) ? 0 : $dstX;
		$dstY = ($dstX < 0) ? 0 : $dstY;
		$dstX = ($dstX > ($dstW / 2)) ? floor ( $dstW / 2 ) : $dstX;
		$dstY = ($dstY > ($dstH / 2)) ? floor ( $dstH / 2 ) : $dstY;
// 		$white = ImageColorAllocate ( $ni, 255, 255, 255 );

// 		$gray = ImageColorAllocate ( $ni, 242, 242, 242 );//灰色
		$black = ImageColorAllocate ( $ni, 0, 0, 0 );
// 		imagefilledrectangle ( $ni, 0, 0, $dstW, $dstH, $gray ); // 填充背景色
		
// 		ImageCopyResized ( $ni, $im, $dstX, $dstY, 0, 0, $fdstW, $fdstH, $srcW, $srcH );
		ImageCopyResized ( $ni, $im, 0, 0, 0, 0, $fdstW, $fdstH, $srcW, $srcH );
	
		if ($markwords != null) {
			$markwords = iconv ( "gb2312", "UTF-8", $markwords );
			//转换文字编码
			ImageTTFText ( $ni, 20, 30, 450, 560, $black, "simhei.ttf", $markwords ); //写入文字水印
			//参数依次为，文字大小|偏转度|横坐标|纵坐标|文字颜色|文字类型|文字内容
		} elseif ($markimage != null) {
			$wimage_data = GetImageSize ( $markimage );
			switch ($wimage_data [2]) {
				case 1 :
					$wimage = @ImageCreateFromGIF ( $markimage );
					break;
				case 2 :
					$wimage = @ImageCreateFromJPEG ( $markimage );
					break;
				case 3 :
					$wimage = @ImageCreateFromPNG ( $markimage );
					break;
				case 4:
					$wimage = @$this->imageCreateFromBMP( $markimage );
					break;
			}
			imagecopy ( $ni, $wimage, 500, 560, 0, 0, 88, 31 ); //写入图片水印,水印图片大小默认为88*31
			imagedestroy ( $wimage );
		}
		ImageJpeg ( $ni, $dstFile, $rate );
		//ImageJpeg ( $ni, $srcFile, $rate );
		imagedestroy ( $im );
		imagedestroy ( $ni );
	}
	
	/**
	 *  获取图片详细信息
	 *  
	 *  @param string $img
	 *  @return array $imginfo
	 */
	public function getImageInfo($img) 
	{
		$imgtype = array ("", "GIF", "JPG", "PNG", "SWF", "PSD", "BMP", "TIFF(intel byte order)", "TIFF(motorola byte order)", "JPC", "JP2", "JPX", "JB2", "SWC", "IFF", "WBMP", "XBM" );
		$Orientation = array ("", "top left side", "top right side", "bottom right side", "bottom left side", "left side top", "right side top", "right side bottom", "left side bottom" );
		$ResolutionUnit = array ("", "", "英寸", "厘米" );
		$YCbCrPositioning = array ("", "the center of pixel array", "the datum point" );
		$ExposureProgram = array ("未定义", "手动", "标准程序", "光圈先决", "快门先决", "景深先决", "运动模式", "肖像模式", "风景模式" );
		$MeteringMode_arr = array ("0" => "未知", "1" => "平均", "2" => "中央重点平均测光", "3" => "点测", "4" => "分区", "5" => "评估", "6" => "局部", "255" => "其他" );
		$Lightsource_arr = array ("0" => "未知", "1" => "日光", "2" => "荧光灯", "3" => "钨丝灯", "10" => "闪光灯", "17" => "标准灯光A", "18" => "标准灯光B", "19" => "标准灯光C", "20" => "D55", "21" => "D65", "22" => "D75", "255" => "其他" );
		$Flash_arr = array ("0" => "flash did not fire", "1" => "flash fired", "5" => "flash fired but strobe return light not detected", "7" => "flash fired and strobe return light detected" );
	
		$exif = exif_read_data ( $img, "IFD0" );
		if ($exif === false) {
			$new_img_info = array ("文件信息" => "没有图片EXIF信息" );
			
		} else {
			
			$exif = exif_read_data ( $img, 0, true );
			
			$new_img_info = array (
				
				"文件信息" => "-----------------------------", 
				"文件名" => $exif [FILE] [FileName], 
				"文件类型" => $imgtype [$exif [FILE] [FileType]], 
				"文件格式" => $exif [FILE] [MimeType], 
				"文件大小" => $exif [FILE] [FileSize], 
				"时间戳" => date ( "Y-m-d H:i:s", $exif [FILE] [FileDateTime] ), 
				"图像信息" => "-----------------------------", 
				"图片说明" => $exif [IFD0] [ImageDescription], 
				"制造商" => $exif [IFD0] [Make], 
				"型号" => $exif [IFD0] [Model], 
				"方向" => $Orientation [$exif [IFD0] [Orientation]], 
				"水平分辨率" => $exif [IFD0] [XResolution] . $ResolutionUnit [$exif [IFD0] [ResolutionUnit]], 
				"垂直分辨率" => $exif [IFD0] [YResolution] . $ResolutionUnit [$exif [IFD0] [ResolutionUnit]], 
				"创建软件" => $exif [IFD0] [Software], 
				"修改时间" => $exif [IFD0] [DateTime], 
				"作者" => $exif [IFD0] [Artist], 
				"YCbCr位置控制" => $YCbCrPositioning [$exif [IFD0] [YCbCrPositioning]], 
				"版权" => $exif [IFD0] [Copyright], 
				"摄影版权" => $exif [COMPUTED] [Copyright . Photographer], 
				"编辑版权" => $exif [COMPUTED] [Copyright . Editor], 
				"拍摄信息" => "-----------------------------", 
				"Exif版本" => $exif [EXIF] [ExifVersion], 
				"FlashPix版本" => "Ver. " . number_format ( $exif [EXIF] [FlashPixVersion] / 100, 2 ), 
				"拍摄时间" => $exif [EXIF] [DateTimeOriginal], 
				"数字化时间" => $exif [EXIF] [DateTimeDigitized], 
				"拍摄分辨率高" => $exif [COMPUTED] [Height], 
				"拍摄分辨率宽" => $exif [COMPUTED] [Width],
			
				/*
				The actual aperture value of lens when the image was taken.
				Unit is APEX.
				To convert this value to ordinary F-number(F-stop),
				calculate this value's power of root 2 (=1.4142).
				For example, if the ApertureValue is '5', F-number is pow(1.41425,5) = F5.6.
				*/
				"光圈" => $exif [EXIF] [ApertureValue], 
				"快门速度" => $exif [EXIF] [ShutterSpeedValue], 
				"快门光圈" => $exif [COMPUTED] [ApertureFNumber], 
				"最大光圈值" => "F" . $exif [EXIF] [MaxApertureValue], 
				"曝光时间" => $exif [EXIF] [ExposureTime], 
				"F-Number" => $exif [EXIF] [FNumber], 
				"测光模式" => $this->getImageInfoVal ( $exif [EXIF] [MeteringMode], $MeteringMode_arr ), 
				"光源" => $this->getImageInfoVal ( $exif [EXIF] [LightSource], $Lightsource_arr ), 
				"闪光灯" => $this->getImageInfoVal ( $exif [EXIF] [Flash], $Flash_arr ), 
				"曝光模式" => ($exif [EXIF] [ExposureMode] == 1 ? "手动" : "自动"), 
				"白平衡" => ($exif [EXIF] [WhiteBalance] == 1 ? "手动" : "自动"), 
				"曝光程序" => $ExposureProgram [$exif [EXIF] [ExposureProgram]],
			
				/*
				Brightness of taken subject, unit is APEX. To calculate Exposure(Ev) from BrigtnessValue(Bv), you must add SensitivityValue(Sv).
				Ev=Bv+Sv   Sv=log((ISOSpeedRating/3.125),2)
				ISO100:Sv=5, ISO200:Sv=6, ISO400:Sv=7, ISO125:Sv=5.32.
				*/
				"曝光补偿" => $exif [EXIF] [ExposureBiasValue] . "EV", 
				"ISO感光度" => $exif [EXIF] [ISOSpeedRatings], 
				"分量配置" => (bin2hex ( $exif [EXIF] [ComponentsConfiguration] ) == "01020300" ? "YCbCr" : "RGB"), //'0x04,0x05,0x06,0x00'="RGB" '0x01,0x02,0x03,0x00'="YCbCr"
				"图像压缩率" => $exif [EXIF] [CompressedBitsPerPixel] . "Bits/Pixel", 
				"对焦距离" => $exif [COMPUTED] [FocusDistance] . "m", 
				"焦距" => $exif [EXIF] [FocalLength] . "mm", 
				"等价35mm焦距" => $exif [EXIF] [FocalLengthIn35mmFilm] . "mm",
			
				/*
				 Stores user comment. This tag allows to use two-byte character code or unicode. First 8 bytes describe the character code. 'JIS' is a Japanese character code (known as Kanji).
				'0x41,0x53,0x43,0x49,0x49,0x00,0x00,0x00':ASCII
				'0x4a,0x49,0x53,0x00,0x00,0x00,0x00,0x00':JIS
				'0x55,0x4e,0x49,0x43,0x4f,0x44,0x45,0x00':Unicode
				'0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00':Undefined
				*/
				"用户注释编码" => $exif [COMPUTED] [UserCommentEncoding], 
				"用户注释" => $exif [COMPUTED] [UserComment], 
				"色彩空间" => ($exif [EXIF] [ColorSpace] == 1 ? "sRGB" : "Uncalibrated"), 
				"Exif图像宽度" => $exif [EXIF] [ExifImageLength], 
				"Exif图像高度" => $exif [EXIF] [ExifImageWidth], 
				"文件来源" => (bin2hex ( $exif [EXIF] [FileSource] ) == 0x03 ? "digital still camera" : "unknown"), 
				"场景类型" => (bin2hex ( $exif [EXIF] [SceneType] ) == 0x01 ? "A directly photographed image" : "unknown"), 
				"缩略图文件格式" => $exif [COMPUTED] [Thumbnail . FileType], 
				"缩略图Mime格式" => $exif [COMPUTED] [Thumbnail . MimeType] 
			);
		}
		return $new_img_info;
	}
	
	public function array2xml($array)
	{
		$xml = "";
		foreach ( $array as $key => $value ) {
			if (is_array ( $value )) {
				$xml .= "<$key>" . $this->array2xml ( $value ) . "</$key>";
			} else {
				$xml .= "<$key>" . $value . "</$key>";
			}
		}
		return $xml;
	}
	
	public function getImageInfoVal($ImageInfo, $val_arr) 
	{
		$InfoVal = "未知";
		foreach ( $val_arr as $name => $val ) {
			if ($name == $ImageInfo) {
				$InfoVal = &$val;
				break;
			}
		}
		return $InfoVal;
	}
	
	/**
	 * 分块读取文件，每块8192bytes
	 * 
	 * @param string $filename
	 * @param unknown_type $retbytes
	 */
	public function readfile_chunked($filename, $retbytes = true) 
	{
		$chunksize =  8*1024; // ~8k chunks 
        $buffer = ''; 
        $cnt =0; 

        $handle = fopen($filename, 'rb'); 
        if ($handle === false) { 
        	return false; 
        } 
           
        while (!feof($handle)) 
        { 
            $buffer = fread($handle, $chunksize); 
            echo $buffer; 
            ob_flush(); 
            flush(); 
            if ($retbytes) { 
                $cnt += strlen($buffer); 
            }
        } 
        
        $status = fclose($handle); 
        if ($retbytes && $status) { 
            return $cnt; // return num. bytes delivered like readfile() does. 
        } 
        return $status; 
        
    }

    /**
     * 从BMP格式图片中获取img
     * @param string $filePath
     */
    private function imageCreateFromBMP($filename)
	{
		//0
		if (! $f1 = fopen($filename,"rb")) return FALSE;
	
		//1
		$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
		if ($FILE['file_type'] != 19778) return FALSE;
	
		//2
		$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
				'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
				'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
		$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
		if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
		$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
		$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
		$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
		$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
		$BMP['decal'] = 4-(4*$BMP['decal']);
		if ($BMP['decal'] == 4) $BMP['decal'] = 0;
	
		//3
		$PALETTE = array();
		if ($BMP['colors'] < 16777216)
		{
			$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
		}
	
		//4
		$IMG = fread($f1,$BMP['size_bitmap']);
		$VIDE = chr(0);
		var_dump($BMP);
		$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
		$P = 0;
		$Y = $BMP['height']-1;
		while ($Y >= 0)
		{
			$X=0;
			while ($X < $BMP['width'])
			{
				if ($BMP['bits_per_pixel'] >= 24) 
				{
					$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
				}
				elseif ($BMP['bits_per_pixel'] == 16)
				{
					$COLOR = unpack("n",substr($IMG,$P,2));
					$COLOR[1] = $PALETTE[$COLOR[1]+1];
				}
				elseif ($BMP['bits_per_pixel'] == 8)
				{
					$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
					$COLOR[1] = $PALETTE[$COLOR[1]+1];
				}
				elseif ($BMP['bits_per_pixel'] == 4)
				{
					$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
					if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
					$COLOR[1] = $PALETTE[$COLOR[1]+1];
				}
				elseif ($BMP['bits_per_pixel'] == 1)
				{
					$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
					if     (($P*8)%8 == 0) $COLOR[1] =  $COLOR[1]        >>7;
					elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
					elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
					elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
					elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
					elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
					elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
					elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
					$COLOR[1] = $PALETTE[$COLOR[1]+1];
				}
				else
					return FALSE;
				imagesetpixel($res,$X,$Y,$COLOR[1]);
				$X++;
				$P += $BMP['bytes_per_pixel'];
			}
			$Y--;
			$P+=$BMP['decal'];
		}
	
		fclose($f1);
		return $res;
	}
	
	
	/**
	 * @param base64的中文名称 $name
	 * @return string
	 */
	private function decodeRequest($name){
		$key = str_replace(" ", "+", $name);
		return base64_decode(str_replace('@@@', '+', $key));
	}
	
	/**
	 * 根据图片比例生成缩略图size
	 * @param 图片宽度 $width
	 * @param 图片高度 $height
	 * @param 默认缩略图宽度 $max
	 * @param 默认缩略图高度 $min
	 * @return array: rate:比率,mode:比例模式,width:宽,height:高
	 */
	private function getRate($width,$height,$max = 800,$min = 600){
		$rData = Array();
	
		if($width>$height){
			$rData['width'] = $max;
			$rData['height'] = $min;
			$rData['mode'] = "2";
		}else{
			$rData['width'] = $min;
			$rData['height'] = $max;
			$rData['mode'] = "3";
		}
	
		//比例 16:9[1.78] 16:10[1.60] 4:3[1.34]
		//比例 9:16[0.56] 10:16[0.62] 3:4[0.75]
		$rate = round($width/$height,2);
		$rData['rate'] = $rate;
	
		//<1 >1 >2
		if($rate == 1){//正方形
			$rData['mode'] = "10";
			$rData['width'] = $max;
			$rData['height'] = $max;
		}
	
		if($rate < 2 &&$rate >= 1.5){//16:9 $rate < 1.8 &&$rate > 1.5
			$rData['mode'] = "20";
			$rData['width'] = $max;
			$rData['height'] = floor($height*$max/$width);
		}
	
		if($rate < 1.5 &&$rate > 1){//4:3 $rate < 1.4 &&$rate > 1.3
			$rData['mode'] = "30";
			$rData['width'] = $max;
			$rData['height'] = $min;
		}
	
		if($rate < 1 &&$rate >= 0.6){//3:4 $rate < 0.8 &&$rate > 0.7
			$rData['mode'] = "31";
			$rData['width'] = $min;
			$rData['height'] = $max;
		}
	
		if($rate < 0.6 &&$rate > 0){//9:16 $rate < 0.6 &&$rate > 0.5
			$rData['mode'] = "21";
			$rData['width'] = floor($width*$min/$height);
			$rData['height'] = $min;
		}
	
		//$this->helper->log(sprintf("mode:%s,w:%s,h:%s,rate:%s",$rData['mode'],$rData['width'],$rData['height'],$rData['rate']));
		//TODO:需要考虑长宽比例尺超过2的图片 vincent20130315
	
		return $rData;
	}
}

